package com.gwthtml.servlet;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.Namespace;
import org.jdom.input.SAXBuilder;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;

public class RemoteHtmlServiceServlet extends RemoteServiceServlet {

	public static final String REMOTE_SERVICE_KEY = "GWT-RemoteService";
	

	public void init(ServletConfig config) throws ServletException {
		super.init(config);
		registerInstance(config, this);
	}
	
	private void registerInstance(ServletConfig config, RemoteHtmlServiceServlet instance) {
		Map<String, RemoteHtmlServiceServlet> services = (Map<String, RemoteHtmlServiceServlet>) config.getServletContext().getAttribute(REMOTE_SERVICE_KEY);
		if (services == null) {
			// No map yet
			services = new HashMap<String, RemoteHtmlServiceServlet>();
			config.getServletContext().setAttribute(REMOTE_SERVICE_KEY, services);
		}
		String urlMapping = parseDeploymentDescriptor(config);
		if (urlMapping != null) {
			services.put(urlMapping, this);
		}
	}

	private String parseDeploymentDescriptor(ServletConfig config) {
		InputStream is = config.getServletContext().getResourceAsStream("/WEB-INF/web.xml");
		if (is != null) {
			try {
				Document doc = new SAXBuilder().build(is);
				Namespace ns = Namespace.getNamespace("http://java.sun.com/xml/ns/j2ee");
				for (Object o :  doc.getRootElement().getChildren("servlet-mapping", ns)) {
					Element e = (Element) o;
					
					String servletName = e.getChild("servlet-name", ns).getValue(); 
					String urlMapping = e.getChild("url-pattern", ns).getValue();
					if (servletName.equals(config.getServletName())) {
						// we have our mapping
						return urlMapping;
					}
				}
			} catch (JDOMException e) {
				throw new RuntimeException(e);
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		}
		return null;
	}

	public Object invoke(Method m, Object[] args, HttpServletRequest request, HttpServletResponse response) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
		try {
			setThreadLocalRequest(request);
			setThreadLocalResponse(response);
			setThreadInCall(true);
			return m.invoke(this, args);
		} finally {
			setThreadInCall(false);
		}
	}
	
}
